package org.dreamwork.telnet;

/**
 * Created by IntelliJ IDEA.
 * User: seth.yang
 * Date: 11-11-10
 * Time: 下午3:59
 */
public class Colorizer {
    private static Object c_Self; //Singleton instance reference
    private int[] m_ColorMapping; //translation table

    /**
     * Constructs a Colorizer with its translation table.
     */
    private Colorizer() {

        m_ColorMapping = new int[ 128];

        m_ColorMapping[ 83] = S;
        m_ColorMapping[ 82] = R;
        m_ColorMapping[ 71] = G;
        m_ColorMapping[ 89] = Y;
        m_ColorMapping[ 66] = B;
        m_ColorMapping[ 77] = M;
        m_ColorMapping[ 67] = C;
        m_ColorMapping[ 87] = W;

        m_ColorMapping[ 115] = s;
        m_ColorMapping[ 114] = r;
        m_ColorMapping[ 103] = g;
        m_ColorMapping[ 121] = y;
        m_ColorMapping[ 98] = b;
        m_ColorMapping[ 109] = m;
        m_ColorMapping[ 99] = c;
        m_ColorMapping[ 119] = w;

        m_ColorMapping[ 102] = f;
        m_ColorMapping[ 100] = d;
        m_ColorMapping[ 105] = i;
        m_ColorMapping[ 106] = j;
        m_ColorMapping[ 117] = u;
        m_ColorMapping[ 118] = v;
        m_ColorMapping[ 101] = e;
        m_ColorMapping[ 110] = n;
        m_ColorMapping[ 104] = h;
        m_ColorMapping[ 97] = a;

        c_Self = this;
    }//constructor

    /**
     * Translates all internal markups within the String
     * into ANSI Escape sequences.<br>
     * The method is hooked into BasicTerminalIO.write(String str), so
     * it is not necessary to call it directly.
     *
     * @param str     String with internal color/style markups.
     * @param support boolean that represents Terminals ability to support GR sequences.
     *                if false, the internal markups are ripped out of the string.
     * @return String with ANSI escape sequences (Graphics Rendition), if support is true,
     *         String without internal markups or ANSI escape sequences if support is false.
     */
    public String colorize( String str, boolean support) {
        return colorize( str, support, false);
    }//colorize

    /**
     * Translates all internal markups within the String
     * into ANSI Escape sequences.<br>
     * The method is hooked into BasicTerminalIO.write(String str), so
     * it is not necessary to call it directly.
     *
     * @param str       String with internal color/style markups.
     * @param support   boolean that represents Terminals ability to support GR sequences.
     *                  if false, the internal markups are ripped out of the string.
     * @param forcebold boolean that forces the output to be bold at any time.
     * @return String with ANSI escape sequences (Graphics Rendition), if support is true,
     *         String without internal markups or ANSI escape sequences if support is false.
     */
    public String colorize( String str, boolean support, boolean forcebold) {

        StringBuffer out = new StringBuffer( str.length() + 20);
        int parsecursor = 0;
        int foundcursor;

        boolean done = false;
        while( !done) {
            foundcursor = str.indexOf( ColorHelper.MARKER_CODE, parsecursor);
            if( foundcursor != -1) {
                out.append( str.substring( parsecursor, foundcursor));
                if( support) {
                    out.append( addEscapeSequence( str.substring( foundcursor + 1, foundcursor + 2), forcebold));
                }
                parsecursor = foundcursor + 2;
            }
            else {
                out.append( str.substring( parsecursor, str.length()));
                done = true;
            }
        }

        /*
         * This will always add a "reset all" escape sequence
         * behind the input string.
         * Basically this is a good idea, because developers tend to
         * forget writing colored strings properly.
         */
        if( support)
            out.append( addEscapeSequence( "a", false));

        return out.toString();
    }//colorize

    private String addEscapeSequence( String attribute, boolean forcebold) {

        StringBuffer tmpbuf = new StringBuffer( 10);

        byte[] tmpbytes = attribute.getBytes();
        int key = (int) tmpbytes[ 0];

        tmpbuf.append( (char) 27);
        tmpbuf.append( (char) 91);
        //tmpbuf.append((new Integer(m_ColorMapping[key])).toString());
        int attr = m_ColorMapping[ key];
        tmpbuf.append( attr);
        if( forcebold && attr != f) {
            tmpbuf.append( (char) 59);
            tmpbuf.append( f);
        }
        tmpbuf.append( (char) 109);

        return tmpbuf.toString();
    }//addEscapeSequence

    /**
     * Returns the reference of the Singleton instance.
     *
     * @return reference to Colorizer singleton instance.
     */
    public static Colorizer getReference() {
        if( c_Self != null) {
            return (Colorizer) c_Self;
        }
        else {
            return new Colorizer();
        }
    }//getReference

    private static void announceResult( boolean res) {
        if( res) {
            System.out.println( "[#" + testcount + "] ok.");
        }
        else {
            System.out.println( "[#" + testcount + "] failed (see possible StackTrace).");
        }
    }//announceResult

    private static int testcount = 0;
    private static Colorizer myColorizer;

    private static void announceTest( String what) {
        testcount++;
        System.out.println( "Test #" + testcount + " [" + what + "]:");
    }//announceTest

    private static void bfcolorTest( String color) {
        System.out.println( "->" + myColorizer.colorize( ColorHelper.boldcolorizeText( "COLOR", color), true) + "<-");
    }//bfcolorTest

    private static void fcolorTest( String color) {
        System.out.println( "->" + myColorizer.colorize( ColorHelper.colorizeText( "COLOR", color), true) + "<-");
    }//fcolorTest

    private static void bcolorTest( String color) {
        System.out.println( "->" + myColorizer.colorize( ColorHelper.colorizeBackground( "     ", color), true) + "<-");
    }//bcolorTest

    public static void main( String[] args) {
        try {
            announceTest( "Instantiation");
            myColorizer = Colorizer.getReference();
            announceResult( true);

            announceTest( "Textcolor Tests");
            fcolorTest( ColorHelper.BLACK);
            fcolorTest( ColorHelper.RED);
            fcolorTest( ColorHelper.GREEN);
            fcolorTest( ColorHelper.YELLOW);
            fcolorTest( ColorHelper.BLUE);
            fcolorTest( ColorHelper.MAGENTA);
            fcolorTest( ColorHelper.CYAN);
            fcolorTest( ColorHelper.WHITE);
            announceResult( true);

            announceTest( "Bold textcolor Tests");
            bfcolorTest( ColorHelper.BLACK);
            bfcolorTest( ColorHelper.RED);
            bfcolorTest( ColorHelper.GREEN);
            bfcolorTest( ColorHelper.YELLOW);
            bfcolorTest( ColorHelper.BLUE);
            bfcolorTest( ColorHelper.MAGENTA);
            bfcolorTest( ColorHelper.CYAN);
            bfcolorTest( ColorHelper.WHITE);
            announceResult( true);

            announceTest( "Background Tests");
            bcolorTest( ColorHelper.BLACK);
            bcolorTest( ColorHelper.RED);
            bcolorTest( ColorHelper.GREEN);
            bcolorTest( ColorHelper.YELLOW);
            bcolorTest( ColorHelper.BLUE);
            bcolorTest( ColorHelper.MAGENTA);
            bcolorTest( ColorHelper.CYAN);
            bcolorTest( ColorHelper.WHITE);
            announceResult( true);

            announceTest( "Mixed Color Tests");
            System.out.println( "->"
                                + myColorizer.colorize( ColorHelper.colorizeText( "COLOR", ColorHelper.WHITE,
                                                ColorHelper.BLUE), true) + "<-");
            System.out.println( "->"
                                + myColorizer.colorize( ColorHelper.colorizeText( "COLOR", ColorHelper.YELLOW,
                                                ColorHelper.GREEN), true) + "<-");
            System.out.println( "->"
                                + myColorizer.colorize( ColorHelper.boldcolorizeText( "COLOR", ColorHelper.WHITE,
                                                ColorHelper.BLUE), true) + "<-");
            System.out.println( "->"
                                + myColorizer.colorize( ColorHelper.boldcolorizeText( "COLOR", ColorHelper.YELLOW,
                                                ColorHelper.GREEN), true) + "<-");

            announceResult( true);

            announceTest( "Style Tests");
            System.out.println( "->" + myColorizer.colorize( ColorHelper.boldText( "Bold"), true) + "<-");
            System.out.println( "->" + myColorizer.colorize( ColorHelper.italicText( "Italic"), true) + "<-");
            System.out.println( "->" + myColorizer.colorize( ColorHelper.underlinedText( "Underlined"), true) + "<-");
            System.out.println( "->" + myColorizer.colorize( ColorHelper.blinkingText( "Blinking"), true) + "<-");

            announceResult( true);

            announceTest( "Mixed Color/Style Tests");
            System.out.println( "->"
                                + myColorizer.colorize( ColorHelper
                                                .boldText( ColorHelper.colorizeText( "RED", ColorHelper.RED, false)
                                                           + ColorHelper.colorizeText( "BLUE", ColorHelper.BLUE, false)
                                                           + ColorHelper.colorizeText( "GREEN", ColorHelper.GREEN,
                                                                           false)), true) + "<-");
            System.out.println( "->"
                                + myColorizer.colorize( ColorHelper
                                                .boldText( ColorHelper.colorizeBackground( "RED", ColorHelper.RED,
                                                                false)
                                                           + ColorHelper.colorizeBackground( "BLUE", ColorHelper.BLUE,
                                                                           false)
                                                           + ColorHelper.colorizeBackground( "GREEN",
                                                                           ColorHelper.GREEN, false)), true) + "<-");
            System.out.println( "->"
                                + myColorizer.colorize( ColorHelper
                                                .boldText( ColorHelper.colorizeText( "RED", ColorHelper.WHITE,
                                                                ColorHelper.RED, false)
                                                           + ColorHelper.colorizeText( "BLUE", ColorHelper.WHITE,
                                                                           ColorHelper.BLUE, false)
                                                           + ColorHelper.colorizeText( "GREEN", ColorHelper.WHITE,
                                                                           ColorHelper.GREEN, false)), true) + "<-");

            announceResult( true);

            announceTest( "Visible length test");
            String colorized = ColorHelper.boldcolorizeText( "STRING", ColorHelper.YELLOW);

            System.out.println( "->" + myColorizer.colorize( colorized, true) + "<-");
            System.out.println( "Visible length=" + ColorHelper.getVisibleLength( colorized));

            colorized = ColorHelper.boldcolorizeText( "BANNER", ColorHelper.WHITE, ColorHelper.BLUE)
                        + ColorHelper.colorizeText( "COLOR", ColorHelper.WHITE, ColorHelper.BLUE)
                        + ColorHelper.underlinedText( "UNDER");
            System.out.println( "->" + myColorizer.colorize( colorized, true) + "<-");
            System.out.println( "Visible length=" + ColorHelper.getVisibleLength( colorized));

            announceResult( true);

/*
            if( false)
                throw new Exception(); //this will shut up jikes
*/

            System.out.println( "Forcing bold");
            System.out.println( myColorizer.colorize( ColorHelper.colorizeText( "RED", ColorHelper.RED), true, true));

        }
        catch( Exception ex) {
            announceResult( false);
            ex.printStackTrace();
        }
    }//main (test routine)

    //Constants
    private static final int S = 30; //black
    private static final int s = 40;
    private static final int R = 31; //red
    private static final int r = 41;
    private static final int G = 32; //green
    private static final int g = 42;
    private static final int Y = 33; //yellow
    private static final int y = 43;
    private static final int B = 34; //blue
    private static final int b = 44;
    private static final int M = 35; //magenta
    private static final int m = 45;
    private static final int C = 36; //cyan
    private static final int c = 46;
    private static final int W = 37; //white
    private static final int w = 47;

    private static final int f = 1; /*bold*/

    private static final int d = 22; /*!bold*///normal color or normal intensity
    private static final int i = 3; /*italic*/
    private static final int j = 23; /*!italic*/
    private static final int u = 4; /*underlined*/
    private static final int v = 24; /*!underlined*/
    private static final int e = 5; /*blink*/
    private static final int n = 25; /*steady = !blink*/
    private static final int h = 8; /*hide = concealed characters*/
    private static final int a = 0; /*all out*/
}